Skip to content

Fix false repo relocation warning on macOS due to NFC/NFD path differences, fixes #2913 (1.4-maint) - #10576

Merged
ThomasWaldmann merged 1 commit into
borgbackup:1.4-maintfrom
ThomasWaldmann:nfd-location-2913-14
Nov 3, 2026
Merged

ThomasWaldmann merged 1 commit into
borgbackup:1.4-maintfrom
ThomasWaldmann:nfd-location-2913-14

Conversation

@ThomasWaldmann

Copy link
Copy Markdown
Member

Backport of #9940 to 1.4-maint. Fixes #2913.

Problem

On macOS the filesystem returns paths in NFD (decomposed) unicode form, while a path typed as a command line argument is usually in NFC (composed) form. They look identical but are byte-different, so accessing a repo whose path contains non-ASCII characters via a relative path / . / $(pwd) made borg believe the repository had been relocated and prompt "The repository at location … was previously located at …".

Fix

  • Add helpers.normalize_local_path(): NFD on macOS, no-op elsewhere.
  • Run local file locations through it in Location.canonical_path().
  • Normalize both sides of the comparison in SecurityManager.assert_location_matches() (in cache.py on 1.4), so existing NFC-form security location files still match after upgrade.

Only affects the repository location string used for the relocation check; archived file paths are unaffected.

Backport notes

Manual port: on 1.4 SecurityManager lives in cache.py and the tests in testsuite/helpers.py.

Testing

  • New tests test_normalize_local_path, test_canonical_path_unicode_normalization; testsuite/helpers.py + testsuite/cache.py pass.
  • Manual repro on macOS/APFS (repo dir created with an NFD name, accessed with an NFC argument): unpatched 1.4-maint shows the bogus relocation prompt, this branch does not.

🤖 Generated with Claude Code

@codecov

codecov Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 82.22%. Comparing base (275ca3c) to head (cb6900b).
⚠️ Report is 16 commits behind head on 1.4-maint.

Additional details and impacted files
@@              Coverage Diff              @@
##           1.4-maint   #10576      +/-   ##
=============================================
+ Coverage      82.10%   82.22%   +0.12%     
=============================================
  Files             38       38              
  Lines          11490    11530      +40     
  Branches        1814     1818       +4     
=============================================
+ Hits            9434     9481      +47     
+ Misses          1467     1465       -2     
+ Partials         589      584       -5     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

…rning on macOS, fixes borgbackup#2913

On macOS the filesystem returns paths in NFD (decomposed) form, while a
path typed as a command line argument is usually in NFC (composed) form.
These look identical but are byte-different, so accessing a repo via a
relative path / `.` / `$(pwd)` after `cd` made borg believe the repository
had been relocated and prompt for confirmation.

Add helpers.normalize_local_path() (NFD on macOS, no-op elsewhere) and run
local file locations through it in Location.canonical_path(). Also normalize
both sides of the location comparison in SecurityManager.assert_location_matches()
so existing NFC-form security "location" files keep matching after upgrade.

This only affects the repository *location* string used for the security /
relocation check (and its display); archived file paths are unaffected, and
the change is a no-op on non-macOS platforms.

Backport of borgbackup#9940 (master commit 4a25abc).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ThomasWaldmann
ThomasWaldmann merged commit cd67fad into borgbackup:1.4-maint Nov 3, 2026
15 checks passed
@ThomasWaldmann
ThomasWaldmann deleted the nfd-location-2913-14 branch November 3, 2026 21:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant